#pragma once

#include "ILCommon.h"
#include "D3DHelper.h"
#include <d3d11.h>
#include "d3dx11effect.h"
#include <d3dx11.h>

#include <vector>

#include "HeightMap.h"
#include "IntPoint.h"
#include "mymath.h"

//forward declartion
class CILApp;
class CTerrain;

//actuall array of nodes on the terrain as oppose to CPath which is the graphical representation
typedef std::vector<IntPoint> Path;

class CTerrainVertex
{
public:
	CTerrainVertex();
	CTerrainVertex(vec3 _pos, vec2 _uv, UINT _index);
	static D3D11_INPUT_ELEMENT_DESC* GetVertexDeclration();

	vec3 m_Position;
	vec3 m_Normal;
	vec2 m_UV;
	UINT m_index;	
};

class CTerrainPatch
{
public:
	CTerrainPatch();
	~CTerrainPatch();

	void CreateMesh(CHeightMap& HeightMap, RECT source, ID3D11Device* pDevice, int index, ID3DX11Effect* pEffect);

	void Render();
	void ComputeNormals();
	void CreateInputLayout();
	IntPoint GetPointFromVertexIndex( int VertexIndex ) const;
	UINT GetSize() const;
private:
	ID3D11Device* m_pDevice;
	ID3D11Buffer* m_pVertexBuffer;
	ID3D11Buffer* m_pIndexBuffer;
	ID3D11InputLayout* m_pInputLayout;

	ID3DX11Effect* m_pEffect;
	CTerrainVertex* m_pVertices;
	UINT m_nVertices;
	UINT m_nTri;
	WORD* m_pIndex;
	UINT m_nIndex;
};

class CMapTile
{
	friend class CTerrain;
public:
	CMapTile();
	void ClearNeighbours();
private:
	int m_type;
	int m_set;
	float m_height;
	float m_cost;
	bool m_walkable;
	CMapTile* m_pNeighbors[8];

	//A* variables
	IntPoint m_MapPos;
	float f, g;
	bool bOpen, bClosed;
	CMapTile* m_pParent;
};

class CPath
{
public:
	CPath();
	CPath( vec3* path, ID3D11Device* pDevice, int PathSize, ID3DX11Effect* pEffect );
	void Render();

	ID3DX11Effect* m_pEffect;
	ID3D11Buffer* m_pVertexBuffer;
	ID3D11InputLayout* m_pInputLayout;
	ID3D11Device* m_pDevice;
	int m_size;
	bool bEmpty;
};
class CTerrain
{
public:
	CTerrain();
	~CTerrain();
	void Init(ID3D11Device* _pDevice, IntPoint _size, CILApp* pApp);
	void CreatePatches(int nPatches);
	void CreateTerrainEffectFile();
	void Render();
	void InitPathFinding();
	CMapTile* GetTile(int x, int y);
	CMapTile* GetTile(IntPoint p);
	bool Within( IntPoint P );
	void CreateTileSets();
	Path GetPath(IntPoint start, IntPoint goal);
	Path GetPath(int StartVertexIndex, int EndVertexIndex);
	void MarkTerrainVertex( int ObjectIndex );
	IntPoint GetPointFromVertexIndex( int VertexIndex ) const;
	UINT GetPatchSize() const;

	// convert a map postion into world position
	vec3 GetWorldPos(IntPoint mapPos);
private:

	CHeightMap* m_pHeightMap;
	IntPoint m_size;
	ID3D11Device* m_pDevice;
	CILApp* m_pApp;
	std::vector<CTerrainPatch*> m_patches;
	ID3DX11Effect* m_pEffect;
	CMapTile* m_pMapTiles;
	UINT m_nTiles;

	// the marked vertices
	UINT m_MarkedVertex[2];

	// the next vertex to be marked
	int m_CurrVertex;
	CPath m_Path;
};